package com.warmheart.core.util.rsa;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * 
 * @ClassName: RsaSignUtil
 * @Description: RSA签名类
 * @author ZhangJianyang
 * @date 2025-06-16 09:37:02
 *
 */
public class RsaSignUtil {

    /** 加密解密算法名称 */
    private static final String ALGORITHM = "RSA";

    /**
     * 签名算法名称
     */
    public static final String SIGN_ALGORITHMS = "MD5withRSA";

    /** Base64 编码/解码器 JDK1.8 */
    private static Base64.Decoder decoder = Base64.getDecoder();

    /** Base64 编码/编码器 JDK1.8 */
    private static Base64.Encoder encoder = Base64.getEncoder();

    /**
     * 使用{@code RSA}方式对字符串进行签名
     * 
     * @param content
     *            需要加签名的数据
     * @param privateKey
     *            {@code RSA}的私钥
     * @param charset
     *            数据的编码方式
     * @return 返回签名信息
     */
    public static String sign(String content, String privateKey, String charset) {
        try {
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoder.decode(privateKey));

            KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);
            PrivateKey priKey = keyf.generatePrivate(keySpec);

            return sign(content, priKey, charset);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 使用{@code RSA}方式对字符串进行签名
     * 
     * @param content
     *            需要加签名的数据
     * @param privateKey
     *            {@code RSA}的私钥
     * @param charset
     *            数据的编码方式
     * @return 返回签名信息
     */
    private static String sign(String content, PrivateKey privateKey, String charset) {
        try {
            Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
            signature.initSign(privateKey);
            signature.update(content.getBytes(charset));
            return encoder.encodeToString(signature.sign());
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 使用{@code MD5withRSA}方式对签名信息进行验证
     * 
     * @param content
     *            需要加签名的数据
     * @param sign
     *            签名信息
     * @param publicKey
     *            {@code RSA}的公钥
     * @param charset
     *            数据的编码方式
     * @return 是否验证通过。{@code True}表示通过
     */
    public static boolean verify(String content, String sign, String publicKey, String charset) {
        try {
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decoder.decode(publicKey));
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            PublicKey pubKey = keyFactory.generatePublic(keySpec);
            return verify(content, sign, pubKey, charset);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 使用{@code MD5withRSA}方式对签名信息进行验证
     * 
     * @param content
     *            需要加签名的数据
     * @param sign
     *            签名信息
     * @param publicKey
     *            {@code RSA}的公钥
     * @param charset
     *            数据的编码方式
     * @return 是否验证通过。{@code True}表示通过
     */
    private static boolean verify(String content, String sign, PublicKey publicKey, String charset) {
        try {
            Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
            signature.initVerify(publicKey);
            signature.update(content.getBytes(charset));
            return signature.verify(decoder.decode(sign));
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

}
